<?php

namespace Romolo\Snitso\Multiplexing;


class Worker
{
    protected $socket;
    public $onConnect = null;
    public $onReceive = null;
    public $onClose = null;

    /**
     * @var array socket 所有连接
     */
    private $sockets = [];

    public function __construct(string $address)
    {
        $this->socket = stream_socket_server($address);

        stream_set_blocking($this->socket, 0);

        $this->sockets[(int) $this->socket] = $this->socket;
    }

    public function start()
    {
        $this->accept();
    }

    private function accept()
    {
        $i = 0;
        while (true) {
            $read = $this->sockets;

            echo '第 '. $i .' 个this->sockets:';
            print_r($read);
            echo '#######################'. PHP_EOL;

            $writes = $excepts = null;

            // 检查池子中可用的连接
            stream_select($read, $writes, $excepts, 0);

            echo '第 '. $i .' 个read：';
            print_r($read);
            echo '#######################'. PHP_EOL;

            foreach ($read as $socket) {
                // $socket 可能是刚刚进来的，也可能是其他 socket
                if ($this->socket === $socket) {
                    // 创建 socket 连接
                    $this->createSocket($i);
                } else {

                    print_r('第 '. $i .' 个this->socket:' . $this->socket);
                    print_r('第 '. $i .' 个socket:' . $socket);
                    echo '#######################'. PHP_EOL;

                    // 如果不是刚进来的 socket，发送消息
                    $this->sendMsg($socket);
                }
            }

            $i++;
        }
    }

    private function createSocket($i)
    {
        $conn = stream_socket_accept($this->socket);

        print_r('第 '. $i .' 个conn:' . $conn);
        echo '#######################' . PHP_EOL;
        ($this->onConnect)($this, $conn);

        // 将创建的 socket 连接存放到 $this->sockets
        $this->sockets[(int)$conn] = $conn;
    }

    private function sendMsg($socket)
    {
        $data = fread($socket, 65535);

        if ($data === '' || $data === false) {
            fclose($socket);
            unset($this->sockets[(int)$socket]);

            return;
        };

        ($this->onReceive)($this, $socket, $data);
    }

    public function send($client, $data)
    {
        fwrite($client, $data);
    }
}